#include <alsa/asoundlib.h>
#include "snowboy/snowboy-detect-c-wrapper.h"

int main()
{
    SnowboyDetect *detector = SnowboyDetectConstructor("common.res", "hqyj.pmdl");
    SnowboyDetectSetSensitivity(detector, "0.5");
    SnowboyDetectSetAudioGain(detector, 1);

    snd_pcm_t* mic;

    //打开录音设备，阻塞方式
    int error = snd_pcm_open(&mic, "hw:0,1", SND_PCM_STREAM_CAPTURE, 0);
    if (error)
    {
        fprintf(stderr, "snd_pcm_open: %s\n", snd_strerror(error));
        return EXIT_FAILURE;
    }

    //设置录音参数
    snd_pcm_hw_params_t * record_param;
    //在栈上分配参数内存并初始化
    snd_pcm_hw_params_alloca(&record_param);
    error += snd_pcm_hw_params_any(mic, record_param);
    //设置采样格式（有符号16位整数，小端序）
    error += snd_pcm_hw_params_set_format(mic, record_param, SND_PCM_FORMAT_S16_LE);
    //设置访问方式（交错读写）
    error += snd_pcm_hw_params_set_access(mic, record_param, SND_PCM_ACCESS_RW_INTERLEAVED);
    //设置采样频率（16KHz）
    error += snd_pcm_hw_params_set_rate(mic, record_param, 16000, 0);
    //设置声道数量（单声道）
    error += snd_pcm_hw_params_set_channels(mic, record_param, 1);
    //根据硬件参数配置声卡
    error = snd_pcm_hw_params(mic, record_param);
    if (error)
    {
        fprintf(stderr, "snd_pcm_hw_params: %s\n", snd_strerror(error));
        return EXIT_FAILURE;
    }

    //获取一个周期数据量，从声卡获取数据时，读写的最小单位是1个周期
    snd_pcm_uframes_t nframe;
    int dir = 0;
    error = snd_pcm_hw_params_get_period_size(record_param, &nframe, &dir);
    if (error)
    {
        fprintf(stderr, "snd_pcm_hw_params_get_period_size: %s\n", snd_strerror(error));
        return EXIT_FAILURE;
    }

    printf("period = %lu frames\n", nframe);
    //分配缓冲区，大小必须为周期的倍数
    char* buf = malloc(snd_pcm_frames_to_bytes(mic, nframe));

    FILE* fp = NULL;
    //记录静音时间
    int silence = 0;

    //开始采集音频
    snd_pcm_prepare(mic);

    while (1)
    {
        snd_pcm_sframes_t rframe;
        //从声卡中读取数据，写入缓冲区
        rframe = snd_pcm_readi(mic, buf, nframe);
        if (rframe < 0)
        {
            fprintf(stderr, "snd_pcm_readi: %s\n", snd_strerror(rframe));
            continue;
        }

        if (fp)
        {
            fwrite(buf, snd_pcm_frames_to_bytes(mic, rframe), 1, fp);
        }

        //返回值：
        // >0 检测到关键词
        // =0 有声音但不是关键词
        // =-1 出错
        // =-2 没有声音
        int result = SnowboyDetectRunDetection(detector, (int16_t *)buf, rframe, 0);
        if (result > 0 && (fp == NULL))
        {
            //开始录音
            puts("recording");
            //暂停采集
            snd_pcm_drop(mic);
            //打开录音文件
            fp = fopen("command.pcm", "w+");
            if (!fp)
            {
                perror("fopen");
            }
            system("aplay -q ding.wav"); //提示录音开始
            //恢复采集
            snd_pcm_prepare(mic);
        }

        if (result == -2 && (fp != NULL))
        {
            //检测到静音并计时
            silence++;
            if (silence > 10)
            {
                //停止录音
                puts("stop");
                //暂停采集
                snd_pcm_drop(mic);
                fclose(fp);
                fp = NULL;
                system("aplay -q dong.wav"); //提示录音结束
                //进行对话
                //asr
                //恢复采集
                snd_pcm_prepare(mic);
            }
        }

        if (result == 0)
        {
            //有声音但不是唤醒词，静音检测时间归零
            silence = 0;
        }
    }

    //停止采集
    snd_pcm_drop(mic);

    free(buf);

    //关闭设备
    snd_pcm_close(mic);

    SnowboyDetectDestructor(detector);
    return 0;
}